export function call(fn, obj, ...args) {
  // 判断obj为ull 或者 undefined就指向全局对象
  if (obj === null || obj === undefined) {
    obj = globalThis; //全局对象
  }
  // 为obj添加临时方法
  obj.temp = fn;
  // 执行临时方法传入参数得到结果
  const reuslt = obj.temp(...args);
  // 删除临时方法
  delete obj.fn;
  // 返回结果
  return reuslt;
}

export function apply(fn, obj, args) {
  // 判断obj为ull 或者 undefined就指向全局对象
  if (obj === null || obj === undefined) {
    obj = globalThis; //全局对象
  }
  // 为obj添加临时方法
  obj.temp = fn;
  // 执行临时方法传入参数得到结果
  const reuslt = obj.temp(...args);
  // 删除临时方法
  delete obj.fn;
  // 返回结果
  return reuslt;
}

export function bind(fn, obj, ...args1) {
  //  返回新函数
  return function (...args2) {
    // 新函数执行call函数返回结果
    return call(fn, obj, ...args1, ...args2);
  };
}

export function debounce(fn, delay) {
  // 定时器变量
  let timerId;
  return function (...args) {
    // 判断
    if (timerId) {
      // 清空定时器
      clearTimeout(timerId);
    }
    // 开启定时器执行函数
    timerId = setTimeout(() => {
      fn.apply(this, args);
      // 执行完成清空当前定时器,防止下次进来走到if逻辑
      timerId = null;
    }, delay);
  };
}

export function throttle(fn, delay) {
  // 定义开始时间
  let start = 0;
  return function (...args) {
    let now = Date.now();
    // 判断 当前时间 - 开始时间大于等于延迟时间
    if (now - start >= delay) {
      // 执行函数
      fn.apply(this, args);
      // 改变开始时间
      start = now;
    }
  };
}

export function forEach(arr, callback) {
  for (let i = 0; i < arr.length; i++) {
    callback(arr[i], i);
  }
}

export function map(arr, callback) {
  // 准备一个数组
  const result = [];
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调函数并传入数组项和索引
    result.push(callback(arr[i], i));
  }
  // 返回重组后的数组
  return result;
}

export function reduce(arr, callback, initValue) {
  // result 赋值为初始值
  let result = initValue;
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调函数传入初始值和数组元素将返回值重新赋值result以便于下次作为回调函数的第一个参数
    result = callback(result, arr[i]);
  }
  // 返回累计结果
  return result;
}

export function filter(arr, callback) {
  // 定义结果数组
  const result = [];
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调函数传入数组项和索引得到返回值
    const res = callback(arr[i], i);
    // 返回值为true推入结果数组
    if (res) {
      result.push(arr[i]);
    }
  }
  // 返回结果数组
  return result;
}

export function find(arr, callback) {
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调函数传入数组项和索引得到返回值
    const res = callback(arr[i], i);
    // 判断为真
    if (res) {
      // 返回当前遍历元素
      return arr[i];
    }
  }
  // 如果返回都不为真则返回undefined
  return undefined;
}

export function findIndex(arr, callback) {
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调函数传入数组项和索引得到返回值
    const res = callback(arr[i], i);
    // 判断为真
    if (res) {
      // 返回当前遍历元素索引
      return i;
    }
  }
  // 如果返回都不为真则返回-1
  return -1;
}

export function every(arr, callback) {
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调 返回值一个为false则返回false
    if (!callback(arr[i], i)) {
      return false;
    }
  }
  // 否则返回true
  return true;
}

export function some(arr, callback) {
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 执行回调 返回值一个为true则返回true
    if (callback(arr[i], i)) {
      return true;
    }
  }
  // 否则返回false
  return false;
}

export function unique1(arr) {
  // Set去重后转换为真正数组
  // return [...new Set(arr)];
  return Array.from(new Set(arr));
}

export function unique2(arr) {
  // 准备结果数组
  const result = [];
  // 循环
  arr.forEach((item) => {
    // 数组不包含此项则推入
    // !result.includes(item)
    if (result.indexOf(item) === -1) {
      result.push(item);
    }
  });
  // 返回结果数组
  return result;
}

export function unique3(arr) {
  // 准备数组和对象
  const result = [];
  const obj = {};
  // 循环
  arr.forEach((item) => {
    // 使用对象key判断 如果不存在则存入
    if (!obj[item]) {
      obj[item] = true;
      result.push(item);
    }
  });
  // 返回结果数组
  return result;
}

export function concat(arr, ...args) {
  // 待合并的数组
  const result = [...arr];
  // 循环 传入的参数数组
  for (let i = 0; i < args.length; i++) {
    // 如果该项是数组则展开推入result数组
    if (Array.isArray(args[i])) {
      result.push(...args[i]);
    } else {
      // 否则直接推入
      result.push(args[i]);
    }
  }
  // 返回
  return result;
}

export function slice(arr, start = 0, end = arr.length) {
  // 当结束小于开始
  if (end < start) {
    end = arr.length;
  }
  // 结果数组
  const result = [];
  // 循环 当索引大于等于开始小于结束时推入
  for (let i = 0; i < arr.length; i++) {
    if (i >= start && i < end) {
      result.push(arr[i]);
    }
  }
  // 返回
  return result;
}

export function flat1(arr) {
  // 准备结果数组
  const result = [];
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // 如果是数组
    if (Array.isArray(arr[i])) {
      // 递归 展开 推入
      result.push(...flat1(arr[i]));
    } else {
      result.push(arr[i]);
    }
  }
  // 返回
  return result;
}

export function flat2(arr) {
  // 浅克隆传入数组 不改变原数组
  let result = [...arr];

  // 当数组里面有一个数组时
  while (result.some((item) => Array.isArray(item))) {
    // 展开合并
    result = [].concat(...result);
  }
  // 返回
  return result;
}

export function chunk(arr, size = 1) {
  // 准备结果和临时数组
  const result = [];
  let temp = [];
  // 遍历
  arr.forEach((item) => {
    // 当临时数组为空推入结果数组
    if (temp.length === 0) {
      result.push(temp);
    }
    // 往临时数组推入数组项
    temp.push(item);
    // 当推入数组项达到传入分块长度时重新赋值空数组循环判断 直到循环结束返回
    if (temp.length === size) {
      temp = [];
    }
  });
  // 返回
  return result;
}

export function difference(arr1, arr2 = []) {
  // 第一个数组过滤每项 判断第二个数组不包含这项就返回此项组成新数组
  return arr1.filter((item) => !arr2.includes(item));
}

export function pull(arr, ...args) {
  // 声明结果数组
  const result = [];
  // 循环
  for (let i = 0; i < arr.length; i++) {
    // args如果包含数组项
    if (args.includes(arr[i])) {
      // 推入
      result.push(arr[i]);
      // 删除当前元素
      arr.splice(i, 1);
      // 下标自减
      i--;
    }
  }
  // 返回被删除的元素组成的数组
  return result;
}

export function pullAll(arr, values) {
  // 第二个参数数组直接解构
  return pull(arr, ...values);
}

export function drop(arr, size = 1) {
  return arr.filter((item, index) => index >= size);
}

export function dropRight(arr, size = 1) {
  return arr.filter((item, index) => index < arr.length - size);
}

export function newInstanceof(Fn, ...args) {
  // 创建一个空对象，继承构造函数的 prototype 属性
  const object = Object.create(Fn.prototype);
  // 执行构造函数
  const result = Fn.call(object, ...args);
  // 如果返回结果是对象，就直接返回，否则返回默认this对象
  return result instanceof Object ? result : object;
}

export function myInstanceof(Fn, obj) {
  // 获取该函数显示原型
  const prototype = Fn.prototype;
  // 获取obj的隐式原型
  let proto = obj.__proto__;
  // 遍历原型链
  while (proto) {
    // 检测原型是否相等
    if (proto === prototype) {
      return true;
    }
    // 如果不等于
    proto = proto.__proto__;
  }
  return false;
}

// Object.create()兼容性写法 函数的功能是以obj为原型创建新对象
export function ceateobject(obj) {
  // 创建一个临时构造函数
  function F() {}
  // 让这个临时构造函数的prototype指向o，这样一来它new出来的对象，__proto__指向了o
  F.prototype = obj;
  // 返回F的实例
  return new F();
}

export function mergeObject(...objs) {
  // 定义合并对象
  const result = {};
  // 遍历对象
  objs.forEach((obj) => {
    // 遍历对象键名
    Object.keys(obj).forEach((key) => {
      // 合并对象存在相同属性
      if (result.hasOwnProperty(key)) {
        // 合并到数组
        result[key] = [].concat(result[key], obj[key]);
      } else {
        // 追加
        result[key] = obj[key];
      }
    });
  });
  // 返回
  return result;
}

export function shallowClone(target) {
  //判断对象数据类型
  if (typeof target === "object" && target !== null) {
    // 判断是否数组
    if (Array.isArray(target)) {
      return [...target];
    } else {
      return { ...target };
    }
  } else {
    return target;
  }
}

export function deepClone1(target) {
  return JSON.parse(JSON.stringify(target));
}

export function deepClone2(target, map = new Map()) {
  // 类型判断
  if (typeof target === "object" && target !== null) {
    // 设置缓存
    const cache = map.get(target);
    // 判断缓存
    if (cache) {
      return cache;
    }
    // 判断容器
    const result = Array.isArray(target) ? [] : {};
    // 设置缓存
    map.set(target, result);
    // 遍历
    for (const key in target) {
      // 判断是否原型
      if (target.hasOwnProperty(key)) {
        result[key] = deepClone2(target[key], map);
      }
    }
    // 返回克隆回的引用数据
    return result;
  } else {
    // 返回基本数据类型
    return target;
  }
}

export function deepClone3(target, map = new Map()) {
  if (typeof target === "object" && target !== null) {
    const cache = map.get(target);
    if (cache) {
      return cache;
    }
    const isArray = Array.isArray(target);
    const result = isArray ? [] : {};
    map.set(target, result);
    // 判断数组
    if (isArray) {
      // 数组
      target.forEach((item, index) => {
        result[index] = deepClone3(item, map);
      });
    } else {
      // 对象
      Object.keys(target).forEach((key) => {
        result[key] = deepClone3(target[key], map);
      });
    }
    return result;
  } else {
    return target;
  }
}

export function reverseString(string) {
  // return string.split("").reverse().join("");
  return [...string].reverse().join("");
}

export function palindrome(string) {
  return reverseString(string) === string;
}

export function truncate(string, size) {
  return string.slice(0, size) + "...";
}

export function addEventListener(el, type, handler, selector) {
  // 判断
  if (typeof el === "string") {
    el = document.querySelector(el);
  }
  // 传入实际要触发事件元素
  if (selector) {
    // 给父元素绑定事件
    el.addEventListener(type, function (e) {
      // 获取实际事件源对象
      const target = e.target;
      // 选择器匹配对应元素
      if (target.matches(selector)) {
        // 执行处理函数传入上下文对象和事件对象
        handler.call(target, e);
      }
    });
  } else {
    el.addEventListener(type, handler);
  }
}

export const dom = {
  // 创建元素 例如dom.create('<div><span>你好</span></div>')
  create(string) {
    // 创建容器   template标签可以容纳任意元素
    const container = document.createElement("template");
    // 要trim，防止拿到空字符
    container.innerHTML = string.trim();
    console.log(container.content.firstChild);
    // 必须要 使用 .content  要不然拿不到
    return container.content.firstChild;
    // 或者
    // return container.content.children[0]
  },

  // 插入后面成为兄弟
  after(node, newNode) {
    // 找到此节点的爸爸然后调用insertBefore（插入某个节点的前面）方法
    //把 newNode 插入到下一个节点的前面
    return node.parentNode.insertBefore(newNode, node.nextSibling);
  },
  // 插入前面成为兄弟
  before(node, newNode) {
    // 正常的返回DOM原生的添加前面的节点的方法即可
    return node.parentNode.insertBefore(newNode, node);
  },
  // 插入子元素
  append(newNode, node) {
    return newNode.appendChild(node);
  },
  // 包裹对应元素 第一个参数被包裹的元素 第二个参数包裹的元素  dom.wrap(test, newDiv)
  // 先把新增的爸爸节点，放到老节点的前面，再把老节点放入新增的爸爸节点的里面
  wrap(node, newNode) {
    // 先把newNode放在node节点的前面   后面也行
    dom.before(node, newNode);
    // 然后把node节点放在newNode里面
    dom.append(newNode, node);
  },
  // 移除对应元素
  remove(node) {
    node.parentNode.removeChild(node);
    //返回删除的节点
    return node;
  },
  // 清空元素内部
  empty(node) {
    let firstChild = node.firstChild,
      array = [];
    while (firstChild) {
      array.push(dom.remove(node.firstChild));
      firstChild = node.firstChild;
    }
    // 返回删除的节点
    return array;
  },
  // 查看设置元素属性 传入两个参数查询属性值 三个值设置属性
  attr(node, name, value) {
    if (arguments.length === 3) {
      // 重载
      // 设置该节点某个属性和属性值
      node.setAttribute(name, value);
    } else if (arguments.length === 2) {
      // 查看该节点某个属性的值
      return node.getAttribute(name);
    }
  },
  // 查看设置元素文本
  text(node, string) {
    if (arguments.length === 2) {
      // 重载
      if ("innerText" in node) {
        // 兼容 ie
        return (node.innerText = string);
      } else {
        return (node.textContent = string);
      }
    } else if (arguments.length === 1) {
      if ("innerText" in node) {
        return node.innerText;
      } else {
        return node.textContent;
      }
    }
  },
  // 查看设置元素内容（包含标签）
  html(node, string) {
    if (arguments.length === 2) {
      node.innerHTML = string;
    } else if (arguments.length === 1) {
      return node.innerHTML;
    }
  },
  // 样式 三个值设置样式，两个值查询样式，统一设置样式可第二个参数传入对象
  style(node, name, value) {
    if (arguments.length === 3) {
      // dom.style(xxx,'color','red')
      node.style[name] = value;
    } else if (arguments.length === 2) {
      if (typeof name === "string") {
        // dom.style(xxx,'color')
        return node.style[name];
      } else if (name instanceof Object) {
        // dom.style(xxx,{color:'red'})
        const object = name;
        for (let key in object) {
          // 不能用 style.key 是因为 key是变量
          node.style[key] = object[key];
        }
      }
    }
  },
  class: {
    // 添加类名
    add(node, className) {
      node.classList.add(className);
    },
    // 移除类名
    remove(node, className) {
      node.classList.remove(className);
    },
    //  元素是否有该类名
    has(node, className) {
      return node.classList.contains(className);
    },
  },
  // 绑定事件
  on(node, eventName, fn) {
    node.addEventListener(eventName, fn);
  },
  // 解绑事件
  off(node, eventName, fn) {
    node.removeEventListener(eventName, fn);
  },
  // 找寻元素
  find(selector, scope) {
    return (scope || document).querySelectorAll(selector);
  },
  // 返回父元素
  parent(node) {
    return node.parentNode;
  },
  // 返回内部所有元素子元素
  children(node) {
    return node.children;
  },
  // 返回所有兄弟
  siblings(node) {
    return Array.from(node.parentNode.children).filter((n) => n !== node);
  },
  // 寻找下一个兄弟元素节点
  next(node) {
    let x = node.nextSibling;
    while (x && x.nodeType === 3) {
      //  1是元素节点， 3是文本节点
      x = x.nextSibling;
    }
    return x;
  },
  // 寻找上一个兄弟元素节点
  previous(node) {
    let x = node.previousSibling;
    while (x && x.nodeType === 3) {
      //  1是元素节点， 3是文本节点
      x = x.previousSibling;
    }
    return x;
  },
  // 遍历节点
  each(nodeList, fn) {
    for (let i = 0; i < nodeList.length; i++) {
      fn.call(null, nodeList[i]);
    }
  },
  // 返回该元素在其父元素的索引
  index(node) {
    // 返回该元素列表
    const list = dom.children(node.parentNode);
    // 遍历
    for (let i = 0; i < list.length; i++) {
      if (list[i] === node) {
        return i;
      }
    }
  },
};
window.dom = dom;

export const eventBus = {
  // 保存类型和回调容器
  callbacks: {
    // login: [fn1, fn2]
  },
};

// 绑定事件
eventBus.on = function (eventName, callback) {
  // 判断有该类型事件
  if (this.callbacks[eventName]) {
    // 推入
    this.callbacks[eventName].push(callback);
  } else {
    // 构造该类型数组
    this.callbacks[eventName] = [callback];
  }
};

// 触发事件
eventBus.emit = function (eventName, data) {
  // 判断有该类型事件
  if (this.callbacks[eventName] && this.callbacks[eventName].length > 0) {
    // 遍历数组里函数执行传入数据
    this.callbacks[eventName].forEach((event) => event(data));
  }
};

eventBus.off = function (eventName) {
  // 如果传入事件名
  if (eventName) {
    // 删除指定事件
    delete this.callbacks[eventName];
  } else {
    // 清空
    this.callbacks = {};
  }
};

export const PubSub = {
  id: 1,
  callbacks: {
    // pay:{
    //   // token_1: fn1,
    //   // token_2: fn2,
    // }
  },
};

PubSub.subscribe = function (channel, callback) {
  // 唯一的编号
  let token = "token_" + this.id++;
  // 判断callbacks是否存在channel
  if (this.callbacks[channel]) {
    // 存入
    this.callbacks[channel][token] = callback;
  } else {
    // 构造出对象存入
    this.callbacks[channel] = {
      [token]: callback,
    };
  }
  return token;
};

// 订阅频道
PubSub.publish = function (channel, data) {
  // 获取当前频道所有的回调 遍历执行
  if (this.callbacks[channel]) {
    Object.values(this.callbacks[channel]).forEach((callback) =>
      callback(data)
    );
  }
};

// 取消订阅
PubSub.unsubscribe = function (flag) {
  // 没有传则全部清空
  if (!flag) {
    this.callbacks = {};
    // 判断
  } else if (typeof flag === "string") {
    // 如果包含token_
    if (flag.includes("token_")) {
      // 遍历对象找到对应token
      const callbackobj = Object.values(this.callbacks).find((obj) =>
        obj.hasOwnProperty(flag)
      );
      if (callbackobj) {
        delete callbackobj[flag];
      }
    } else {
      // 删除该订阅下所有回调
      delete this.callbacks[flag];
    }
  }
};

export function axios({ method, url, params, data }) {
  // Promise风格
  return new Promise((resolve, reject) => {
    // 1.创建xhr对象
    const xhr = new XMLHttpRequest();
    // 设置响应类型为json
    xhr.responseType = "json";
    // 2.监听事件 处理响应
    xhr.onreadystatechange = function () {
      if (xhr.readyState !== 4) return;
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
        // 传递响应信息
        resolve({
          status: xhr.status,
          message: xhr.statusText,
          data: xhr.response,
        });
      } else {
        // 请求失败, 调用 reject(reason)
        reject(new Error("请求失败: status: " + xhr.status));
      }
    };
    // 方法转为大写
    method = method.toUpperCase();
    // 拼接params对象 a=1&b=2
    let str = "";
    for (let key in params) {
      str += `${key}=${params[key]}&`;
    }
    str = str.slice(0, -1);
    url += url.includes("?") ? "&" : "?";

    // 3.准备发送请求
    xhr.open(method, url + str, true);

    // 如果请求不为get则携带请求体参数
    if (method === "POST" || method === "PUT" || method === "DELETE") {
      xhr.setRequestHeader("Content-type", "application/json");
      xhr.send(JSON.stringify(data));
    } else {
      xhr.send(null);
    }
  });
}

axios.get = function (url, options = {}) {
  const conifg = Object.assign(options, { method: "GET", url });
  return axios(conifg);
};

axios.post = function (url, options = {}) {
  const conifg = Object.assign(options, { method: "POST", url });
  return axios(conifg);
};

axios.put = function (url, options = {}) {
  const conifg = Object.assign(options, { method: "PUT", url });
  return axios(conifg);
};

axios.delete = function (url, options = {}) {
  const conifg = Object.assign(options, { method: "DELETE", url });
  return axios(conifg);
};

export function MyPromise(executor) {
  // promise的状态和值
  this.promiseState = "pending";
  this.promiseResult = null;
  // 保存成功和失败回调
  this.callbacks = [];
  const resolve = (value) => {
    //  判断状态
    if (this.promiseState !== "pending") return;
    // 更改为成功状态和值
    this.promiseState = "fulfilled";
    this.promiseResult = value;
    // 遍历执行成功的回调
    setTimeout(() => {
      this.callbacks.forEach((stateObj) => {
        stateObj.onResolved(value);
      });
    });
  };
  const reject = (reason) => {
    //  判断状态
    if (this.promiseState !== "pending") return;
    // 更改为失败状态和值
    this.promiseState = "rejected";
    this.promiseResult = reason;
    // 遍历执行失败的回调
    setTimeout(() => {
      this.callbacks.forEach((stateObj) => {
        stateObj.onRejected(reason);
      });
    });
  };
  // throw抛出错误走到reject
  try {
    executor(resolve, reject);
  } catch (e) {
    reject(e);
  }
}

// 添加then方法
MyPromise.prototype.then = function (onResolved, onRejected) {
  // 如果不传递成功或者失败的回调函数 默认构造一个
  if (typeof onResolved !== "function") {
    onResolved = (value) => value;
  }
  if (typeof onRejected !== "function") {
    onRejected = (reason) => {
      throw reason;
    };
  }

  return new MyPromise((resolve, reject) => {
    const callback = (type) => {
      try {
        // 获取回调函数执行结果
        const result = type(this.promiseResult);
        // 判断
        if (result instanceof MyPromise) {
          // 如果是Promise类型对象
          result.then(
            (res) => {
              resolve(res);
            },
            (reason) => {
              reject(reason);
            }
          );
        } else {
          // 状态变为成功
          resolve(result);
        }
      } catch (e) {
        reject(e);
      }
    };
    // 执行then成功回调
    if (this.promiseState === "fulfilled") {
      setTimeout(() => {
        callback(onResolved);
      });
    }
    // 执行then失败回调
    if (this.promiseState === "rejected") {
      setTimeout(() => {
        callback(onRejected);
      });
    }
    // 若为pending保存成功和失败回调
    if (this.promiseState === "pending") {
      this.callbacks.push({
        onResolved: () => {
          callback(onResolved);
        },
        onRejected: () => {
          callback(onRejected);
        },
      });
    }
  });
};

// catch实例方法
MyPromise.prototype.catch = function (onRejected) {
  return this.then(undefined, onRejected);
};

// finally实例方法
MyPromise.prototype.finally = function (callback) {
  return this.then(
    (value) => {
      return MyPromise.resolve(callback()).then(() => value);
    },
    (reason) => {
      return MyPromise.resolve(callback()).then(() => {
        throw reason;
      });
    }
  );
};

// resolve静态方法
MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => {
    if (value instanceof MyPromise) {
      value.then(
        (res) => {
          resolve(res);
        },
        (reason) => {
          reject(reason);
        }
      );
    } else {
      resolve(value);
    }
  });
};

// reject静态方法
MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => {
    reject(reason);
  });
};

// all静态方法
MyPromise.all = function (promises) {
  // 计数
  let count = 0;
  let arr = [];
  return new MyPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (value) => {
          // 有一个成功的Promise就+1 直到全部成功
          count++;
          arr[i] = value;
          if (count === promises.length) {
            resolve(arr);
          }
        },
        (reason) => {
          reject(reason);
        }
      );
    }
  });
};

// race静态方法
MyPromise.race = function (promises) {
  return new MyPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (value) => {
          resolve(value);
        },
        (reason) => {
          reject(reason);
        }
      );
    }
  });
};

// 手写Promise
// class MyPromise {
//   constructor(executor) {
//     // promise的状态和值
//     this.promiseState = "pending";
//     this.promiseResult = null;
//     // 保存成功和失败回调
//     this.callbacks = [];
//     const resolve = (value) => {
//       //  判断状态
//       if (this.promiseState !== "pending") return;
//       // 更改为成功状态和值
//       this.promiseState = "fulfilled";
//       this.promiseResult = value;
//       // 遍历执行成功的回调
//       setTimeout(() => {
//         this.callbacks.forEach((stateObj) => {
//           stateObj.onResolved(value);
//         });
//       });
//     };
//     const reject = (reason) => {
//       //  判断状态
//       if (this.promiseState !== "pending") return;
//       // 更改为失败状态和值
//       this.promiseState = "rejected";
//       this.promiseResult = reason;
//       // 遍历执行失败的回调
//       setTimeout(() => {
//         this.callbacks.forEach((stateObj) => {
//           stateObj.onRejected(reason);
//         });
//       });
//     };
//     // throw抛出错误走到reject
//     try {
//       executor(resolve, reject);
//     } catch (e) {
//       reject(e);
//     }
//   }
//   then(onResolved, onRejected) {
//     // 如果不传递成功或者失败的回调函数 默认构造一个
//     if (typeof onResolved !== "function") {
//       onResolved = (value) => value;
//     }
//     if (typeof onRejected !== "function") {
//       onRejected = (reason) => {
//         throw reason;
//       };
//     }

//     return new MyPromise((resolve, reject) => {
//       const callback = (type) => {
//         try {
//           // 获取回调函数执行结果
//           const result = type(this.promiseResult);
//           // 判断
//           if (result instanceof MyPromise) {
//             // 如果是Promise类型对象
//             result.then(
//               (res) => {
//                 resolve(res);
//               },
//               (reason) => {
//                 reject(reason);
//               }
//             );
//           } else {
//             // 状态变为成功
//             resolve(result);
//           }
//         } catch (e) {
//           reject(e);
//         }
//       };
//       // 执行then成功回调
//       if (this.promiseState === "fulfilled") {
//         setTimeout(() => {
//           callback(onResolved);
//         });
//       }
//       // 执行then失败回调
//       if (this.promiseState === "rejected") {
//         setTimeout(() => {
//           callback(onRejected);
//         });
//       }
//       // 若为pending保存成功和失败回调
//       if (this.promiseState === "pending") {
//         this.callbacks.push({
//           onResolved: () => {
//             callback(onResolved);
//           },
//           onRejected: () => {
//             callback(onRejected);
//           },
//         });
//       }
//     });
//   }
//   catch(onRejected) {
//     return this.then(undefined, onRejected);
//   }
//   finally(callback) {
//     return this.then(
//       (value) => {
//         return MyPromise.resolve(callback()).then(() => value);
//       },
//       (reason) => {
//         return MyPromise.resolve(callback()).then(() => {
//           throw reason;
//         });
//       }
//     );
//   }
//   static resolve(value) {
//     return new MyPromise((resolve, reject) => {
//       if (value instanceof MyPromise) {
//         value.then(
//           (res) => {
//             resolve(res);
//           },
//           (reason) => {
//             reject(reason);
//           }
//         );
//       } else {
//         resolve(value);
//       }
//     });
//   }
//   static reject(reason) {
//     return new MyPromise((resolve, reject) => {
//       reject(reason);
//     });
//   }
//   static all(promises) {
//     // 计数
//     let count = 0;
//     let arr = [];
//     return new MyPromise((resolve, reject) => {
//       for (let i = 0; i < promises.length; i++) {
//         promises[i].then(
//           (value) => {
//             // 有一个成功的Promise就+1 直到全部成功
//             count++;
//             arr[i] = value;
//             if (count === promises.length) {
//               resolve(arr);
//             }
//           },
//           (reason) => {
//             reject(reason);
//           }
//         );
//       }
//     });
//   }
//   static race(promises) {
//     return new MyPromise((resolve, reject) => {
//       for (let i = 0; i < promises.length; i++) {
//         promises[i].then(
//           (value) => {
//             resolve(value);
//           },
//           (reason) => {
//             reject(reason);
//           }
//         );
//       }
//     });
//   }
// }

// 数据类型判断
export function typeOf(data) {
  return Object.prototype.toString.call(data).slice(8, -1);
}

export function once(fn) {
  // 标识 用于控制函数只执行一次
  let done = false;
  return function (...args) {
    // 判断
    if (!done) {
      done = true;
      // 执行函数
      fn.call(this, ...args);
    }
  };
}

// 柯里化
export function curry(fn) {
  // 返回柯里化后函数
  return function curryFn(...args1) {
    // 如果形参和实参相同 调用函数传入对应数量的参数
    if (fn.length === args1.length) return fn(...args1);
    // 参数不够时返回函数累积参数
    return (...args2) => curryFn(...args1, ...args2);
  };
}

export function getParams(url) {
  const result = {};
  if (url.includes("?")) {
    // 截取道？后面的参数 user=yunmu&age=16
    const str = url.split("?")[1];
    // 分割为 ['user=yunmu', 'age=16']
    const arr = str.split("&");
    // 遍历后赋值对面key value对
    arr.forEach((item) => {
      const key = item.split("=")[0];
      const val = item.split("=")[1];
      result[key] = decodeURIComponent(val); // 解码
    });
  }
  // 返回
  return result;
}

const strList = "qhshdggsvvxggtsggsggeyyytwwwwwwwwwww";
const obj = {};
for (var i = 0; i < strList.length; i++) {
  let str = strList.charAt(i);
  if (obj[str]) {
    obj[str]++;
  } else {
    obj[str] = 1;
  }
}

let max = 0;
let maxNumber = "";
for (var i in obj) {
  if (obj[i] > max) {
    max = obj[i];
    maxNumber = i;
  }
}
console.log("max:", max); //11
console.log("maxNumber:", maxNumber); //w
